package com.sys.midware.rdb.handler;

import java.io.Reader;
import java.sql.Connection;
import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;

import com.sys.midware.logger.Logger;
import com.sys.midware.logger.LoggerFactory;

public class MyBatisUtil {
    private static Logger logger = LoggerFactory.getLogger(MyBatisUtil.class);

    private static final String MYBATIS_CONFIG_FILE_DEFAULT = "mybatis-config.xml";

    // private static SqlSessionFactory sqlSessionFactory = null;

    private static Map<String, SqlSessionFactory> sqlSessionFactoryCached = new HashMap<String, SqlSessionFactory>();

    private static final ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();

    private static TransactionFactory transactionFactory = new JdbcTransactionFactory();

    private MyBatisUtil() {

    }

    // static {
    // buildSessionFactory();
    // }

    // /**
    // * 获取SqlSessionFactory
    // * @param
    // * @return SqlSessionFactory
    // */
    // public static SqlSessionFactory getSqlSessionFactory() {
    // if (sqlSessionFactory == null) {
    // buildSessionFactory();
    // }
    // return sqlSessionFactory;
    // }
    /**
     * 
     * @param
     * @return SqlSession
     */
    public static SqlSession getSession() {
        return getSession(null, null);
    }

    /**
     * 获取session
     * 
     * @return SqlSession
     */
    public static SqlSession getSession(Connection conn, String mybatisConfig) {
        SqlSession session = threadLocal.get();
        String mybatisKey = (mybatisConfig == null ? MYBATIS_CONFIG_FILE_DEFAULT : mybatisConfig);
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryCached.get(mybatisKey);
        if (sqlSessionFactory == null) {
            buildSessionFactory(mybatisConfig);
            sqlSessionFactory = sqlSessionFactoryCached.get(mybatisKey);
        }
        session = openSession(sqlSessionFactory, conn);
        threadLocal.set(session);

        return session;
    }

    private static SqlSession openSession(SqlSessionFactory sqlSessionFactory, Connection conn) {
        if (sqlSessionFactory == null) {
            return null;
        }
        // 如果未设置connection,则走默认
        if (conn == null) {
            return sqlSessionFactory.openSession();
        }
        return sqlSessionFactory.openSession(conn);
    }

    /**
     * 关闭session
     */
    public static void closeSession() {
        SqlSession session = threadLocal.get();
        if (session != null) {
            session.close();
            threadLocal.set(null);
        }
    }

    public static TransactionFactory getTransactionFactory() {
        return transactionFactory;
    }

    /**
     * sqlSessionFactory 直接从配置读取
     * 
     * @param
     * @return void
     */
    private static void buildSessionFactory(String mybatisConfig) {
        SqlSessionFactory sqlSessionFactory = null;
        try {
            // 直接加载配置文件
            String resource = mybatisConfig == null ? MYBATIS_CONFIG_FILE_DEFAULT : mybatisConfig;
            Reader reader = Resources.getResourceAsReader(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
            sqlSessionFactoryCached.put(resource, sqlSessionFactory);
            logger.info("--buildSessionFactory,sqlSessionFactoryCached:" + sqlSessionFactoryCached);

        } catch (Exception e) {
            logger.error("创建SessionFactory失败，异常信息：" + e.getMessage());
            e.printStackTrace();
        } finally {

        }
    }

    /**
     * 根据datasource创建sessionFactory
     * 
     * @param
     * @return void
     */
    public static void buildSessionFactory(DataSource ds) {
        SqlSessionFactory sqlSessionFactory = null;
        try {
            // Mybatis 环境和配置
            Environment environment = new Environment.Builder("development").// 环境id
                    transactionFactory(transactionFactory).dataSource(ds).build();

            Configuration conf = new Configuration(environment);
            conf.setEnvironment(environment);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(conf);
            logger.info("----" +sqlSessionFactory);
        } catch (Exception e) {
            logger.error("创建SessionFactory失败，异常信息：" + e.getMessage());
            e.printStackTrace();
        } finally {

        }
    }

    /**
     * 根据包名加入mapper
     * 
     * @param
     * @return void
     */
    public static void addMapper(SqlSessionFactory sqlSessionFactory, String mapperPackageName) {
        if (sqlSessionFactory != null) {
            sqlSessionFactory.getConfiguration().addMappers(mapperPackageName);
        }
    }
}
